#include "geom_cal_2d.h"
namespace qbe::auxiliary {

//直线一般式转两点式
line toline(double a, double b, double c) {
  if (sign(b) == 0)
    exit(1);
  point A(0, -c / b), B(-c / a, 0);
  return line(A, B);
}
//直线两点式转一般式
line2 toline2(point a, point b) {
  double A = b.y - a.y, B = a.x - b.x, C = -B * a.y - A * a.x;
  return line2(A, B, C);
}
//点p绕o逆时针旋转alpha
point rotate(point o, point p, double alpha) {
  point tp;
  p.x -= o.x;
  p.y -= o.y;
  tp.x = p.x * cos(alpha) - p.y * sin(alpha) + o.x;
  tp.y = p.y * cos(alpha) + p.x * sin(alpha) + o.y;
  return tp;
}
//向量u的倾斜角
double angle(point u) {
  return atan2(u.y, u.x);
}
//oe与os的夹角，夹角正负满足叉积
double angle(point o, point s, point e) {
  point os = s - o, oe = e - o;
  double bot = sqrt(dmult(os, os) * dmult(oe, oe));
  double top = dmult(os, oe);
  double cosfi = top / bot;
  if (cosfi >= 1.0)
    return 0;
  if (cosfi <= -1.0)
    return -Pi;
  double fi = acos(cosfi);
  if (xmult(o, s, e) > 0)
    return fi;
  else
    return -fi;
}

//判点在线段上
int p_on_seg(point a, point p1, point p2) {
  if (fabs(xmult(a, p1, p2)) <= eps && (a.x - p1.x) * (a.x - p2.x) < eps && (a.y - p1.y) * (a.y - p2.y) < eps)
    return 1;
  return 0;
}
//判点在线段端点左方
int p_on_segvex(point s, point p) {
  return fabs(p.y - s.y) < eps && (p.x <= s.x + eps);
}
//判线段相交 <=:不规范相交
int seg_inter(line s, line p) {
  double minx1 = min(s.a.x, s.b.x), maxx1 = max(s.a.x, s.b.x);
  double minx2 = min(p.a.x, p.b.x), maxx2 = max(p.a.x, p.b.x);
  double miny1 = min(s.a.y, s.b.y), maxy1 = max(s.a.y, s.b.y);
  double miny2 = min(p.a.y, p.b.y), maxy2 = max(p.a.y, p.b.y);
  if ((minx1 > maxx2 + eps) || (minx2 > maxx1 + eps) || (miny1 > maxy2 + eps) || (miny2 > maxy1 + eps))
    return 0;
  else
    return sign(xmult(s.a, s.b, p.a) * xmult(s.a, s.b, p.b)) <= 0 &&
           sign(xmult(p.a, p.b, s.a) * xmult(p.a, p.b, s.b)) <= 0;
}
//判点在多边形内部
int p_in_polygon(point a, point p[], int n) {
  int count = 0;
  line s, ps;
  ps.a = a, ps.b = a;
  ps.b.x = inf;
  for (int i = 0; i < n; i++) {
    s.a = p[i];
    if (i + 1 < n)
      s.b = p[i + 1];
    else
      s.b = p[0];
    if (s.a.y > s.b.y)
      swap(s.a, s.b);
    if (p_on_seg(a, s.a, s.b))
      return 2;
    if ((fabs(s.a.y - s.b.y) > eps)) {
      if (p_on_segvex(s.b, a))
        count++;
      else if (seg_inter(ps, s))
        count++;
    }
  }
  if (count % 2)
    return 1;
  return 0;
}
}